home *** CD-ROM | disk | FTP | other *** search
- /*
- **
- ** BITWISE.C Bit-wise operations on floating point numbers.
- **
- ** Written 11-15-92 in ANSI C
- **
- ** Eval is a floating point expression evaluator.
- ** This file last updated in version 1.10
- ** For the version number, see eval.h
- ** Copyright (C) 1993 Will Menninger
- **
- ** This program is free software; you can redistribute it and/or modify it
- ** under the terms of the GNU General Public License as published by the
- ** Free Software Foundation; either version 2 of the License, or any
- ** later version.
- **
- ** This program is distributed in the hope that it will be useful, but
- ** WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- ** General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License along
- ** with this program; if not, write to the Free Software Foundation, Inc.,
- ** 675 Mass Ave, Cambridge, MA 02139, USA.
- **
- ** The author until 9/93 can be contacted at:
- ** e-mail: willus@ilm.pfc.mit.edu
- ** U.S. mail: Will Menninger, 45 River St., #2, Boston, MA 02108-1124
- **
- **
- */
-
- #include "eval.h"
-
- #define DATASIZE ((DBL_MANT_DIG>>3)+2)
-
- typedef unsigned char uchar;
- typedef struct {
- uchar data[DATASIZE];
- int sign;
- int mask;
- int numbits;
- int exponent;
- int mi;
- } BITARRAY, *BITARRAYPTR;
-
- static void dbl_to_ba(double val,BITARRAYPTR ba);
- static double ba_to_dbl(BITARRAYPTR ba);
- static void change_exp(BITARRAYPTR ba,int newexp);
- static void shift_right(BITARRAYPTR ba,int count);
- static void shift_left(BITARRAYPTR ba,int count);
- static void ba_negate(BITARRAYPTR ba);
- static void ba_not(BITARRAYPTR ba);
- #ifdef DEBUG
- static void print_ba(BITARRAYPTR ba);
- #endif
-
-
- double not(double val)
-
- {
- BITARRAY ba;
-
- dbl_to_ba(val,&ba);
- ba_not(&ba);
- ba_negate(&ba);
- ba.sign=!ba.sign;
- return(ba_to_dbl(&ba));
- }
-
-
- double or(double val1,double val2)
-
- {
- BITARRAY ba1,ba2;
- int i;
-
- dbl_to_ba(val1,&ba1);
- dbl_to_ba(val2,&ba2);
- if (ba1.exponent>ba2.exponent)
- change_exp(&ba2,ba1.exponent);
- else
- change_exp(&ba1,ba2.exponent);
- if (!ba1.sign)
- ba_negate(&ba1);
- if (!ba2.sign)
- ba_negate(&ba2);
- for (i=0;i<=ba1.mi;i++)
- ba1.data[i]|=ba2.data[i];
- ba1.data[ba1.mi]&=ba1.mask;
- if (!ba1.sign || !ba2.sign)
- {
- ba_negate(&ba1);
- ba1.sign=0;
- }
- else
- ba1.sign=1;
- return(ba_to_dbl(&ba1));
- }
-
-
- double and(double val1,double val2)
-
- {
- BITARRAY ba1,ba2;
- int i;
-
- dbl_to_ba(val1,&ba1);
- dbl_to_ba(val2,&ba2);
- if (ba1.exponent>ba2.exponent)
- change_exp(&ba2,ba1.exponent);
- else
- change_exp(&ba1,ba2.exponent);
- if (!ba1.sign)
- ba_negate(&ba1);
- if (!ba2.sign)
- ba_negate(&ba2);
- for (i=0;i<=ba1.mi;i++)
- ba1.data[i]&=ba2.data[i];
- ba1.data[ba1.mi]&=ba1.mask;
- if (!ba1.sign && !ba2.sign)
- {
- ba_negate(&ba1);
- ba1.sign=0;
- }
- else
- ba1.sign=1;
- return(ba_to_dbl(&ba1));
- }
-
-
- double xor(double val1,double val2)
-
- {
- BITARRAY ba1,ba2;
- int i;
-
- dbl_to_ba(val1,&ba1);
- dbl_to_ba(val2,&ba2);
- if (ba1.exponent>ba2.exponent)
- change_exp(&ba2,ba1.exponent);
- else
- change_exp(&ba1,ba2.exponent);
- if (!ba1.sign)
- ba_negate(&ba1);
- if (!ba2.sign)
- ba_negate(&ba2);
- for (i=0;i<=ba1.mi;i++)
- ba1.data[i]^=ba2.data[i];
- ba1.data[ba1.mi]&=ba1.mask;
- if ((!ba1.sign && ba2.sign)||(ba1.sign && !ba2.sign))
- {
- ba_negate(&ba1);
- ba1.sign=0;
- }
- else
- ba1.sign=1;
- return(ba_to_dbl(&ba1));
- }
-
-
- static void dbl_to_ba(double val,BITARRAYPTR ba)
-
- {
- int i,j,k,m;
- double f;
-
- ba->numbits=DBL_MANT_DIG-3;
- ba->mask=0;
- ba->mi=0;
- ba->exponent=0;
- ba->sign=(val>=0.);
- val=fabs(val);
- if (val>0.)
- {
- f=log(val)/log(2.);
- f=floor(f)+1.;
- ba->exponent=f;
- f=val/pow(2.,f);
- f=f+pow(2.,(double)-ba->numbits-1.);
- if (f>=1.)
- {
- ba->exponent++;
- f/=2.;
- }
- }
- else
- f=0.;
- for (i=0;i<DATASIZE;i++)
- ba->data[i]=0;
- for (i=0,j=0,k=128;i<ba->numbits;i++)
- {
- f=f*2.;
- if (f>=1.)
- {
- ba->data[j]|=k;
- f-=1.;
- }
- k>>=1;
- if (!k)
- {
- j++;
- k=128;
- }
- }
- if (k==128)
- {
- ba->mask=255;
- ba->mi=j-1;
- }
- else
- {
- for (k<<=1,m=k;k<128;k<<=1,m|=k);
- ba->mask=m;
- ba->mi=j;
- }
- }
-
-
- static double ba_to_dbl(BITARRAYPTR ba)
-
- {
- int i,j,k;
- double val;
-
- val=0.;
- for (i=0,j=0,k=128;i<ba->numbits;i++,k>>=1)
- {
- if (!k)
- {
- k=128;
- j++;
- }
- val=val*2.;
- if (ba->data[j]&k)
- val=val+1.;
- }
- val=val*pow(2.,(double)ba->exponent-ba->numbits);
- return(ba->sign ? val : -val);
- }
-
-
- static void change_exp(BITARRAYPTR ba,int newexp)
-
- {
- if (newexp>ba->exponent)
- shift_right(ba,newexp-ba->exponent);
- else
- shift_left(ba,ba->exponent-newexp);
- ba->exponent=newexp;
- }
-
-
- static void shift_right(BITARRAYPTR ba,int count)
-
- {
- int i,j,k,m;
- int smallshift;
- int byteshift;
-
- if (!count)
- return;
- if (count>=ba->numbits)
- {
- for (i=0;i<DATASIZE;i++)
- ba->data[i]=0;
- return;
- }
- smallshift=count&7;
- if (smallshift)
- {
- m=1;
- for (i=1;i<smallshift;i++)
- m=(m<<1)|1;
- k=0;
- for (i=0;i<=ba->mi;i++)
- {
- j=ba->data[i];
- if (i>0)
- ba->data[i]=k|(j>>smallshift);
- else
- ba->data[i]=j>>smallshift;
- k=(j&m)<<(8-smallshift);
- }
- }
- byteshift=(count>>3);
- if (byteshift)
- {
- for (i=ba->mi;i>=byteshift;i--)
- ba->data[i]=ba->data[i-byteshift];
- for (i=byteshift-1;i>=0;i--)
- ba->data[i]=0;
- }
- ba->data[ba->mi]&=ba->mask;
- }
-
-
- static void shift_left(BITARRAYPTR ba,int count)
-
- {
- int i,j,k,m;
- int smallshift;
- int byteshift;
-
- if (!count)
- return;
- if (count>=ba->numbits)
- {
- for (i=0;i<DATASIZE;i++)
- ba->data[i]=0;
- return;
- }
- smallshift=count&7;
- if (smallshift)
- {
- m=128;
- for (i=1;i<smallshift;i++)
- m=(m>>1)|128;
- k=0;
- ba->data[ba->mi]&=ba->mask;
- for (i=ba->mi;i>=0;i--)
- {
- j=ba->data[i];
- if (i<ba->mi)
- ba->data[i]=k|(j<<smallshift);
- else
- ba->data[i]=j<<smallshift;
- k=(j&m)>>(8-smallshift);
- }
- }
- byteshift=(count>>3);
- if (byteshift)
- {
- for (i=0;i<=ba->mi-byteshift;i++)
- ba->data[i]=ba->data[i+byteshift];
- for (i=ba->mi-byteshift+1;i<=ba->mi;i++)
- ba->data[i]=0;
- }
- ba->data[ba->mi]&=ba->mask;
- }
-
-
- static void ba_negate(BITARRAYPTR ba)
-
- {
- int i,j,k,one;
-
- i=ba->numbits&7;
- if (!i)
- i=8;
- k=128;
- for (j=1;j<i;j++,k>>=1);
- j=ba->mi;
- one=0;
- for (i=ba->numbits-1;i>=0;i--,k<<=1)
- {
- if (k>128)
- {
- k=1;
- j--;
- if (one)
- break;
- }
- if (one)
- ba->data[j]^=k;
- else
- if (ba->data[j]&k)
- {
- one=1;
- if (i==ba->numbits-1)
- ba->data[j]^=k;
- }
- }
- if (i>0)
- for (;j>=0;j--)
- ba->data[j]=~ba->data[j];
- }
-
-
-
- static void ba_not(BITARRAYPTR ba)
-
- {
- int i;
-
- for (i=0;i<=ba->mi;i++)
- ba->data[i]=~ba->data[i];
- ba->data[ba->mi]&=ba->mask;
- }
-
-
- #ifdef DEBUG
- static void print_ba(BITARRAYPTR ba)
-
- {
- int i;
-
- printf(ba->sign ? "+" : "-");
- for (i=0;i<ba->mi;i++)
- printf("%02X",(unsigned)ba->data[i]);
- printf("%02X %d\n",(unsigned)ba->data[ba->mi]&ba->mask,
- ba->exponent);
- }
- #endif
-